package com.cinema.service;

import com.cinema.dao.*;
import com.cinema.dao.impl.*;
import com.cinema.entity.*;
import com.cinema.exception.SeatException;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 基于数据库的电影院服务实现
 */
public class CinemaServiceDB implements CinemaServiceInterface {
    
    private final UserDao userDao = new UserDaoImpl();
    private final MovieDao movieDao = new MovieDaoImpl();
    private final ScreeningRoomDao roomDao = new ScreeningRoomDaoImpl();
    private final ScheduleDao scheduleDao = new ScheduleDaoImpl();
    private final TicketDao ticketDao = new TicketDaoImpl();
    
    // 用户管理
    @Override
    public void addUser(User user) {
        if (userDao.userExists(user.getId())) {
            throw new RuntimeException("用户已存在: " + user.getId());
        }
        userDao.addUser(user);
    }
    
    @Override
    public User getUser(String id) {
        return userDao.getUserById(id);
    }
    
    @Override
    public List<User> getAllUsers() {
        return userDao.getAllUsers();
    }
    
    @Override
    public void updateUser(User user) {
        userDao.updateUser(user);
    }
    
    @Override
    public void deleteUser(String id) {
        userDao.deleteUser(id);
    }
    
    // 电影管理
    @Override
    public void addMovie(Movie movie, User operator) {
        checkPermission(operator, "添加电影");
        if (movieDao.movieExists(movie.getId())) {
            throw new RuntimeException("电影已存在: " + movie.getId());
        }
        movieDao.addMovie(movie);
    }
    
    @Override
    public Movie getMovie(String id) {
        return movieDao.getMovieById(id);
    }
    
    @Override
    public List<Movie> getAllMovies() {
        return movieDao.getAllMovies();
    }
    
    // 放映厅管理
    @Override
    public void addRoom(ScreeningRoom room, User operator) {
        checkPermission(operator, "添加放映厅");
        if (roomDao.roomExists(room.getId())) {
            throw new RuntimeException("放映厅已存在: " + room.getId());
        }
        roomDao.addRoom(room);
    }
    
    @Override
    public ScreeningRoom getRoom(String id) {
        return roomDao.getRoomById(id);
    }
    
    @Override
    public List<ScreeningRoom> getAllRooms() {
        return roomDao.getAllRooms();
    }
    
    @Override
    public void deleteRoom(String id, User operator) {
        checkPermission(operator, "删除放映厅");
        roomDao.deleteRoom(id);
    }
    
    // 排片管理
    @Override
    public void addSchedule(Schedule schedule, User operator) {
        checkPermission(operator, "添加排片");
        if (scheduleDao.scheduleExists(schedule.getId())) {
            throw new RuntimeException("排片已存在: " + schedule.getId());
        }
        
        // 检查时间冲突
        if (scheduleDao.hasTimeConflict(schedule.getRoom().getId(), 
                                       schedule.getStartTime(), 
                                       schedule.getEndTime(), 
                                       null)) {
            throw new RuntimeException("时间冲突：该放映厅在指定时间段已有排片");
        }
        
        scheduleDao.addSchedule(schedule);
    }
    
    @Override
    public Schedule getSchedule(String id) {
        return scheduleDao.getScheduleById(id);
    }
    
    @Override
    public List<Schedule> getAllSchedules() {
        return scheduleDao.getAllSchedules();
    }
    
    @Override
    public void deleteSchedule(String id, User operator) {
        checkPermission(operator, "删除排片");
        scheduleDao.deleteSchedule(id);
    }
    
    // 查询功能
    @Override
    public List<Schedule> queryByMovie(String movieName) {
        // 先根据电影名称找到电影ID
        List<Movie> movies = movieDao.getAllMovies();
        for (Movie movie : movies) {
            if (movie.getName().equals(movieName)) {
                return scheduleDao.getSchedulesByMovie(movie.getId());
            }
        }
        return List.of();
    }
    
    @Override
    public List<Schedule> queryByRoom(String roomId) {
        return scheduleDao.getSchedulesByRoom(roomId);
    }
    
    @Override
    public List<Schedule> queryByTime(LocalDateTime startTime, LocalDateTime endTime) {
        return scheduleDao.getSchedulesByTimeRange(startTime, endTime);
    }
    
    @Override
    public List<Movie> getCurrentMovies() {
        LocalDateTime now = LocalDateTime.now();
        List<Schedule> currentSchedules = scheduleDao.getSchedulesByTimeRange(now, now.plusDays(7));
        
        return currentSchedules.stream()
                .map(Schedule::getMovie)
                .distinct()
                .toList();
    }
    
    // 售票功能
    @Override
    public void sellTicket(String scheduleId, int row, int col, String phone, User operator) throws SeatException {
        checkPermission(operator, "售票");
        
        Schedule schedule = scheduleDao.getScheduleById(scheduleId);
        if (schedule == null) {
            throw new RuntimeException("排片不存在: " + scheduleId);
        }
        
        // 检查座位是否有效
        if (row < 0 || row >= schedule.getRoom().getRows() || 
            col < 0 || col >= schedule.getRoom().getCols()) {
            throw new SeatException("座位不存在: " + row + "-" + col);
        }
        
        // 检查座位是否已售
        if (ticketDao.isSeatOccupied(scheduleId, row, col)) {
            throw new SeatException("座位已售出: " + row + "-" + col);
        }
        
        // 执行售票
        ticketDao.sellTicket(scheduleId, row, col, phone, operator.getId());
        
        // 更新内存中的座位状态
        schedule.sellSeat(row, col, phone);
    }
    
    // 座位状态查询
    @Override
    public boolean[][] getSeatStatus(String scheduleId) {
        Schedule schedule = scheduleDao.getScheduleById(scheduleId);
        if (schedule == null) {
            throw new RuntimeException("排片不存在: " + scheduleId);
        }
        
        return ticketDao.getSeatStatus(scheduleId, schedule.getRoom().getRows(), schedule.getRoom().getCols());
    }
    
    @Override
    public TicketDao.SeatStatistics getSeatStatistics(String scheduleId) {
        return ticketDao.getSeatStatistics(scheduleId);
    }
    
    @Override
    public List<TicketDao.TicketRecord> getTicketRecords(String scheduleId) {
        return ticketDao.getTicketRecords(scheduleId);
    }
    
    // 权限检查
    private void checkPermission(User user, String operation) {
        if (user == null) {
            throw new RuntimeException("用户未登录，无法执行操作: " + operation);
        }
        
        // 管理员可以执行所有操作
        if (user.getRole() == Role.ADMIN) {
            return;
        }
        
        // 店长可以执行大部分操作，但不能删除用户
        if (user.getRole() == Role.MANAGER) {
            if (operation.equals("删除用户")) {
                throw new RuntimeException("权限不足，无法执行操作: " + operation);
            }
            return;
        }
        
        // 售票员只能售票和查询
        if (user.getRole() == Role.CASHIER) {
            if (!operation.equals("售票") && !operation.startsWith("查询")) {
                throw new RuntimeException("权限不足，无法执行操作: " + operation);
            }
            return;
        }
        
        throw new RuntimeException("未知用户角色，无法执行操作: " + operation);
    }
    
    // 兼容模式支持（用于第一轮迭代的测试用例）
    @Override
    public void addMovie(Movie movie) {
        addMovie(movie, null);
    }
    
    @Override
    public void addRoom(ScreeningRoom room) {
        addRoom(room, null);
    }
    
    @Override
    public void addSchedule(Schedule schedule) {
        addSchedule(schedule, null);
    }
    
    @Override
    public void sellTicket(String scheduleId, int row, int col, String phone) throws SeatException {
        sellTicket(scheduleId, row, col, phone, null);
    }
} 